package com.xxg.renrenorder.dao;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Indexes;
import com.mongodb.client.result.UpdateResult;
import com.xxg.renrencommon.domain.filedenum.orderenum.AfterSalesOrderStatusEnum;
import com.xxg.renrencommon.domain.filedenum.orderenum.OrderStatusEnum;
import com.xxg.renrencommon.exception.ErrorMessage;
import com.xxg.renrencommon.exception.OrderManagerException;
import com.xxg.renrenorder.dao.bean.OperationInfo;
import com.xxg.renrenorder.dao.bean.OrderMasterInfo;
import com.xxg.renrenorder.dao.bean.ProductInfo;
import com.xxg.renrenorder.domain.query.OrderListQuery;
import com.xxg.renrenorder.domain.result.ProductInfoResult;
import org.bson.Document;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.query.Criteria.where;

/**
 * 订单表Dao
 *
 * @author xxg
 * @date 2020/11/16
 */
@Repository
public class OrderMasterInfoDao {
    private final MongoTemplate mongoTemplate;

    public OrderMasterInfoDao(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
        createCollection();
    }

    /**
     * 创建collection
     */
    private void createCollection() {
        String collectionName = "orderMasterInfo";
        MongoCollection<Document> collection;
        if (!mongoTemplate.getCollectionNames().contains(collectionName)) {
            collection = mongoTemplate.createCollection(OrderMasterInfo.class);
            createIndex(collection);
        }
    }

    /**
     * 创建索引
     *
     * @param collection 数据集
     */
    private void createIndex(MongoCollection<Document> collection) {
        collection.createIndex(Indexes.compoundIndex(Indexes.ascending("userId"),
                Indexes.ascending("deleted"), Indexes.ascending("orderStatus")));
        collection.createIndex(Indexes.descending("createTime"));
        collection.createIndex(Indexes.ascending("orderStatus"));
    }

    /**
     * 分页获取特定用户特定状态的订单
     *
     * @param userId      会员ID
     * @param orderStatus 订单状态
     * @param pageNo      页码
     * @param pageSize    页大小
     * @return 订单列表
     */
    public List<OrderMasterInfo> getOrdersByUserId(Integer userId, Integer orderStatus, Integer pageNo, Integer pageSize) {
        int start = pageNo * pageSize;
        Query query = new Query(where("userId").is(userId).and("deleted").is(false));
        if (orderStatus != null) {
            query = new Query(where("userId").is(userId).and("deleted").is(false).and("orderStatus").is(orderStatus));
        }
        query.with(Sort.by(Sort.Order.desc("createTime")));
        query.skip(start).limit(pageSize);
        return mongoTemplate.find(query, OrderMasterInfo.class);
    }

    /**
     * 分页获取特定用户特定状态的订单
     *
     * @param orderStatus 订单状态
     * @param pageNo      页码
     * @param pageSize    页大小
     * @param spuId       spuId
     * @return 订单列表
     */
    public List<OrderMasterInfo> getOrders(Integer orderStatus, Integer pageNo, Integer pageSize, String spuId) {
        int start = pageNo * pageSize;
        Query query = new Query(where("deleted").is(false));
        if (orderStatus != null) {
            query = new Query(where("deleted").is(false).and("orderStatus").is(orderStatus));
        }
        if (spuId != null) {
            query.addCriteria(Criteria.where("productInfos.spuId").is(spuId));
        }
        query.with(Sort.by(Sort.Order.desc("createTime")));
        query.skip(start).limit(pageSize);
        return mongoTemplate.find(query, OrderMasterInfo.class);
    }

    /**
     * 统计出不同状态的订单数量（不含售后订单）
     *
     * @param userId 会员ID
     * @return 结果
     */
    public int[] getOrdersCountByStatus(String userId) {
        Aggregation agg = newAggregation(match(where("userId").is(userId).and("deleted").is(false).and("orderStatus").lt(4)),
                group("orderStatus")
                        .first("orderStatus").as("orderStatus").count().as("count"),
                sort(Sort.by(Sort.Order.asc("orderStatus"))));
        AggregationResults<OrderMasterInfo> results = mongoTemplate.aggregate(agg, OrderMasterInfo.class,
                OrderMasterInfo.class);
        List<OrderMasterInfo> orderMasterInfos = results.getMappedResults();
        int[] ints = {0, 0, 0};
        for (OrderMasterInfo info : orderMasterInfos) {
            switch (info.getOrderStatus()) {
                case 1:
                    // 待付款
                    ints[0] = info.getCount();
                    break;
                case 2:
                    // 待发货
                    ints[1] = info.getCount();
                    break;
                case 3:
                    // 待收货
                    ints[2] = info.getCount();
                    break;
                default:
                    break;
            }
        }
        return ints;
    }

    /**
     * 根据订单ID查询订单详情
     *
     * @param orderId 订单ID
     * @return 订单详情
     */
    public OrderMasterInfo getOrderByOrderId(String orderId) {
        Query query = new Query(where("_id").is(orderId));
        return mongoTemplate.findOne(query, OrderMasterInfo.class);
    }

    /**
     * 根据订单ID删除用户自己的订单
     *
     * @param id     订单ID
     * @param userId 会员ID
     */
    public void removeOrderByIdUserId(String id, Integer userId) {
        // 处于结束状态的订单可删除
        Query query = new Query(where("_id").is(id).and("userId").is(userId)
                .and("orderStatus").in(OrderStatusEnum.SUCCESS.getValue(),
                        OrderStatusEnum.CLOSED.getValue(), OrderStatusEnum.RETURNED_PAID.getValue()));
        Update update = new Update();
        update.set("deleted", true);
        update.set("updateTime", new Date());
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 分页获取所有用户的订单
     *
     * @param orderStatus    订单状态
     * @param pageNo         页码
     * @param pageSize       页大小
     * @param dates          开始时间结束时间
     * @param orderListQuery 其他查询条件
     * @return 订单列表
     */
    public List<OrderMasterInfo> getAllOrdersByStatus(List<Integer> orderStatus, Integer pageNo, Integer pageSize, Date[] dates, OrderListQuery orderListQuery, Integer shopId) {
        int start = pageNo * pageSize;
        Query query = genOrdersByStatusQuery(orderStatus, dates, orderListQuery, shopId);
        if (orderListQuery.getSortField() != null && orderListQuery.getSortField().trim().length() > 0) {
            if (orderListQuery.getSort() == null || orderListQuery.getSort() == 0 ) {
                query.with(Sort.by(Sort.Order.desc(orderListQuery.getSortField())));
            }else {
                query.with(Sort.by(Sort.Order.asc(orderListQuery.getSortField())));
            }
        }else {
            query.with(Sort.by(Sort.Order.desc("createTime")));
        }
        query.skip(start).limit(pageSize);
        return mongoTemplate.find(query, OrderMasterInfo.class);
    }

    /**
     * 统计数量
     *
     * @param orderStatus    订单状态
     * @param dates          开始时间结束时间
     * @param orderListQuery 其他查询条件
     * @return 数量
     */
    public long countAllOrdersByStatus(List<Integer> orderStatus, Date[] dates, OrderListQuery orderListQuery, Integer shopId) {
        Query query = genOrdersByStatusQuery(orderStatus, dates, orderListQuery, shopId);
        return mongoTemplate.count(query, OrderMasterInfo.class);
    }

    private Query genOrdersByStatusQuery(List<Integer> orderStatus, Date[] dates, OrderListQuery orderListQuery, Integer shopId) {
        Query query;
        if (orderStatus == null) {
            query = new Query();
        } else {
            query = new Query(where("orderStatus").in(orderStatus));
        }
        if (dates != null) {
            query.addCriteria(where("createTime").gte(dates[0]).lte(dates[1]));
        }
        if (orderListQuery != null) {
            if (orderListQuery.getUserId() != null && orderListQuery.getUserId() > 0) {
                query.addCriteria(where("userId").is(orderListQuery.getUserId()));
            }
            if (shopId != null && shopId > 0) {
                query.addCriteria(where("shopId").is(shopId));
            }
            if (orderListQuery.getGroupId() != null && orderListQuery.getGroupId().size() > 0) {
                query.addCriteria(where("userGroupId").in(orderListQuery.getGroupId()));
            }
            if (orderListQuery.getName() != null && orderListQuery.getName().trim().length() > 0) {
                String regx = "^.*" + orderListQuery.getName().trim() + ".*$";
                query.addCriteria(where("addressInfo.name").regex(regx));
            }
            if (orderListQuery.getPhone() != null && orderListQuery.getPhone().trim().length() > 0) {
                query.addCriteria(where("addressInfo.phone").is(orderListQuery.getPhone().trim()));
            }
            if (orderListQuery.getAreaCode() != null) {
                query.addCriteria(where("addressInfo.areaCode").is(orderListQuery.getAreaCode()));
            }
            if (orderListQuery.getProductName() != null && orderListQuery.getProductName().trim().length() > 0) {
                query.addCriteria(where("productInfos.spuName").regex(orderListQuery.getProductName()));
            }
            if (orderListQuery.getShopName() != null && orderListQuery.getShopName().trim().length() > 0) {
                query.addCriteria(where("productInfos.shopName").regex(orderListQuery.getProductName()));
            }
            if (orderListQuery.getOrderType() != null) {
                query.addCriteria(where("orderType").is(orderListQuery.getOrderType()));
            }
        }
        return query;
    }

    /**
     * 批量更新订单快递物流信息
     *
     * @param ids       订单号
     * @param expCodes  快递公司代码
     * @param expNos    快递单号
     * @param expImages 快递图片
     * @param remark    快递备注
     * @throws OrderManagerException 异常信息
     */
    public void setOrderExpress(List<Long> ids, List<String> expCodes, List<String> expNos, List<String> expImages, List<String> remark) throws OrderManagerException {
        BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, OrderMasterInfo.class);
        int len = ids.size();
        if (len != expCodes.size() || len != expNos.size()) {
            throw new OrderManagerException(ErrorMessage.SIZE_NOT_SAME);
        }
        List<Pair<Query, Update>> updateList = new ArrayList<>(len);
        Date updateTime = new Date();
        for (int i = 0; i < len; i++) {
            Query query = new Query(where("_id").is(ids.get(i)));
            Update update = new Update();
            update.set("expressInfo.expCode", expCodes.get(i));
            update.set("expressInfo.expNo", expNos.get(i));
            if (expImages != null && expImages.size() > i) {
                update.set("expressInfo.expImage", expImages.get(i));
            }
            if (remark != null && remark.size() > i) {
                update.set("expressInfo.remark", remark.get(i));
            }
            update.set("updateTime", updateTime);
            update.set("expressTime", updateTime);
            update.set("orderStatus", OrderStatusEnum.UN_COMMIT.getValue());
            Pair<Query, Update> updatePair = Pair.of(query, update);
            updateList.add(updatePair);
        }
        operations.updateMulti(updateList);
        operations.execute();
    }

    /**
     * 更新订单状态
     *
     * @param query  查询条件
     * @param status 状态
     */
    private int updateOrderStatus(Query query, int status) {
        Update update = new Update();
        update.set("updateTime", new Date());
        update.set("orderStatus", status);
        update.set("doneTime", new Date());
        UpdateResult result = mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
        return (int) result.getModifiedCount();
    }

    /**
     * 更新订单状态和支付信息
     *
     * @param query        查询条件
     * @param status       订单状态
     * @param payType      支付方式
     * @param tradeNo      交易号
     * @param tradeTime    交易时间
     * @param tradeStatus  交易状态
     * @param payException 订单金额与支付金额不一致
     */
    private void updateOrderTradeStatus(Query query, int status, Integer payType, String tradeNo, String tradeTime,
                                        String tradeStatus, Boolean payException) {
        Update update = new Update();
        update.set("updateTime", new Date());
        update.set("orderStatus", status);
        update.set("payException", payException);
        update.set("paymentInfo.paymentType", payType);
        update.set("paymentInfo.gmtPayment", tradeTime);
        update.set("paymentInfo.tradeNo", tradeNo);
        update.set("paymentInfo.tradeStatus", tradeStatus);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 取消订单
     *
     * @param id     订单ID
     * @param userId 会员ID
     */
    public int cancelOrderById(String id, Integer userId) {
        // 待付款的订单才允许取消
        Query query = new Query(where("_id").is(id).and("userId").is(userId)
                .and("orderStatus").is(OrderStatusEnum.UN_PAID.getValue()));
        return updateOrderStatus(query, OrderStatusEnum.CLOSED.getValue());
    }

    /**
     * 取消订单（超时未支付，系统自动取消）
     *
     * @param id 订单ID
     */
    public int cancelOrderById(String id) {
        // 待付款的订单才允许取消
        Query query = new Query(where("_id").is(id).and("orderStatus").is(OrderStatusEnum.UN_PAID.getValue()));
        return updateOrderStatus(query, OrderStatusEnum.CLOSED.getValue());
    }

    /**
     * 支付超时关闭订单
     *
     * @param id          订单ID
     * @param payType     支付方式
     * @param tradeNo     支付交易号
     * @param tradeTime   支付时间
     * @param tradeStatus 支付状态
     */
    public void cancelOrder(Long id, Integer payType, String tradeNo, String tradeTime, String tradeStatus) {
        Query query = new Query(where("_id").is(id).and("orderStatus").is(OrderStatusEnum.UN_PAID.getValue()));
        updateOrderTradeStatus(query, OrderStatusEnum.CLOSED.getValue(),
                payType, tradeNo, tradeTime, tradeStatus, false);
    }

    /**
     * 确认收货
     *
     * @param id 订单ID
     * @param shopId
     */
    public void commitOrderById(String id, Integer shopId) {
        // 待收货的订单才允许确认收货
        Query query = new Query(where("_id").is(id).and("orderStatus").is(OrderStatusEnum.UN_COMMIT.getValue()));
        if (shopId != null) {
            query.addCriteria(Criteria.where("shopId").is(shopId));
        }
        updateOrderStatus(query, OrderStatusEnum.SUCCESS.getValue());
    }

    /**
     * 订单已付款
     *
     * @param id           订单ID
     * @param payType      支付方式
     * @param tradeNo      支付交易号
     * @param tradeTime    支付时间
     * @param tradeStatus  支付状态
     * @param payException 订单金额与支付金额是否不对，false-一致，true-不一致
     */
    public void setOrderPayment(String id, Integer payType, String tradeNo, String tradeTime, String tradeStatus, Boolean payException) {
        OrderMasterInfo order = getOrderByOrderId(id);
        Query query = new Query(where("_id").is(id));
        updateOrderTradeStatus(query, OrderStatusEnum.UN_EXPRESS.getValue(),
                payType, tradeNo, tradeTime, tradeStatus, payException);
    }

    /**
     * 设置订单的支付方式方便后面查询
     *
     * @param id      订单ID
     * @param payType 支付方式
     */
    public void setOrderPaymentType(Long id, Integer payType) {
        Query query = new Query(where("_id").is(id));
        Update update = new Update();
        update.set("updateTime", new Date());
        update.set("paymentInfo.paymentType", payType);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 更新订单中的明细
     *
     * @param orderMasterInfo 订单信息
     */
    public void updatePayDetail(OrderMasterInfo orderMasterInfo) {
        Query query = new Query(where("_id").is(orderMasterInfo.getId()));
        Update update = new Update();
        update.set("updateTime", new Date());
        update.set("totalDiscount", orderMasterInfo.getTotalDiscount());
        update.set("totalPay", orderMasterInfo.getTotalPay());
        update.set("productInfos", orderMasterInfo.getProductInfos());
        update.set("paymentInfo", orderMasterInfo.getPaymentInfo());
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 设置订单支付的状态（关闭状态）
     *
     * @param orderId     订单ID
     * @param payType     支付方式
     * @param tradeNo     支付交易号
     * @param tradeTime   交易时间
     * @param tradeStatus 交易状态
     */
    public void setPaymentStatus(Long orderId, Integer payType, String tradeNo, String tradeTime, String tradeStatus) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("updateTime", new Date());
        update.set("paymentInfo.paymentType", payType);
        update.set("paymentInfo.gmtPayment", tradeTime);
        update.set("paymentInfo.tradeNo", tradeNo);
        update.set("paymentInfo.tradeStatus", tradeStatus);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 订单已全额退款
     *
     * @param orderId     订单ID
     * @param payType     支付方式
     * @param tradeNo     支付交易号
     * @param tradeTime   交易时间
     * @param tradeStatus 交易状态
     */
    public void setAllReturnPaid(String orderId, Integer payType, String tradeNo, String tradeTime, String tradeStatus) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("updateTime", new Date());
        update.set("orderStatus", OrderStatusEnum.RETURNED_PAID.getValue());
        update.set("paymentInfo.paymentType", payType);
        update.set("paymentInfo.gmtRefund", tradeTime);
        update.set("paymentInfo.tradeStatus", tradeStatus);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 插入订单信息
     *
     * @param orderMasterInfo 订单信息
     */
    public void submitOrder(OrderMasterInfo orderMasterInfo) {
        orderMasterInfo.setCreateTime(new Date());
        orderMasterInfo.setUpdateTime(new Date());
        mongoTemplate.insert(orderMasterInfo);
    }

    /**
     * 修改订单价格
     *
     * @param orderMasterInfo 订单信息
     */
    public void editOrder(OrderMasterInfo orderMasterInfo) {
        mongoTemplate.save(orderMasterInfo);
    }

    /**
     * 更新订单中的商品售后状态
     *
     * @param orderId 订单ID
     * @param skuId   商品ID
     * @param status  售后状态
     */
    public void updateProductStatus(String orderId, Integer skuId, Integer status) {
        Query query = new Query(where("_id").is(orderId).and("productInfos.skuId").is(skuId));
        Update update = new Update();
        update.set("productInfos.$.afterSalesStatus", status);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 订单确认收货后超过15天关闭售后
     *
     * @param id 订单ID
     */
    public void closeAfterSales(String id) {
        Query query = new Query(where("_id").is(id));
        Update update = new Update();
        update.set("closeAfterSales", true);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 设置物流运费
     *
     * @param id          订单ID
     * @param expressCost 运费
     * @return 修改的记录数
     */
    public long setOrderExpressCost(Long id, BigDecimal expressCost) {
        // 更新运费
        Query query = new Query(where("_id").is(id));
        Update update = new Update();
        update.set("expressInfo.expressPay", expressCost);
        UpdateResult result = mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
        return result.getModifiedCount();
    }

    /**
     * 查询用户未评价的商品
     *
     * @param userId 会员ID
     * @return 未评价商品数量
     */
    public int getUnCommentSkuCount(String userId) {
        Aggregation agg = newAggregation(unwind("productInfos"),
                match(where("userId").is(userId).and("deleted").is(false).and("orderStatus").is(4)
                        .and("closeAfterSales").is(null).and("productInfos.hasComment").is(null)),
                project("productInfos"));
        AggregationResults<ProductInfo> results = mongoTemplate.aggregate(agg, OrderMasterInfo.class,
                ProductInfo.class);
        List<ProductInfo> productInfos = results.getMappedResults();
        return productInfos.size();
    }

    /**
     * 查询用户未评价和已评价商品列表
     *
     * @param userId 会员ID
     * @return 未评价和已评价商品列表
     */
    public List<ProductInfoResult> getSkuCommentList(String userId) {
        Aggregation agg = newAggregation(unwind("productInfos"),
                match(where("userId").is(userId).and("deleted").is(false).and("orderStatus").is(4)
                        .and("closeAfterSales").is(null)),
                project("productInfos").andInclude("productInfos.skuId", "productInfos.spuId",
                        "productInfos.photo", "productInfos.spuName", "productInfos.skuName",
                        "productInfos.price", "productInfos.number", "productInfos.hasComment", "productInfos.comment", "id"));
        AggregationResults<ProductInfoResult> results = mongoTemplate.aggregate(agg, OrderMasterInfo.class,
                ProductInfoResult.class);
        return results.getMappedResults();
    }

    /**
     * 根据会员ID查询其未完成的订单列表
     *
     * @param userId   客户ID
     * @param date     邀请日期
     * @param pageNo   页码
     * @param pageSize 页大小
     * @return 订单列表
     */
    public List<OrderMasterInfo> getUnFinishOrderByUserId(String userId, Date date, Integer pageNo, Integer pageSize) {
        Query query = new Query(where("userId").is(userId).and("deleted").is(false).and("orderStatus").lt(4).and("createTime").gte(date));
        query.with(Sort.by(Sort.Order.desc("createTime")));
        int start = pageNo * pageSize;
        query.skip(start).limit(pageSize);
        return mongoTemplate.find(query, OrderMasterInfo.class);
    }

    /**
     * 更新订单中已退的运费
     *
     * @param id                 订单ID
     * @param refundExpressFee   已退运费
     * @param unRefundExpressFee 没有退还的运费
     */
    public void updateRefundExpressFee(Long id, BigDecimal refundExpressFee, BigDecimal unRefundExpressFee) {
        Query query = new Query(where("_id").is(id));
        Update update = new Update();
        update.set("updateTime", new Date());
        if (refundExpressFee != null) {
            update.set("refundExpressFee", refundExpressFee);
        }
        if (unRefundExpressFee != null) {
            update.set("unRefundExpressFee", unRefundExpressFee);
        }
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 员工更新订单全局的备注
     *
     * @param orderId        订单ID
     * @param employeeRemark 备注信息
     */
    public void updateEmployeeRemark(Long orderId, String employeeRemark) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("employeeRemark", employeeRemark);
        update.set("employeeRemarkIsRead", false);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 编辑员工备注已读
     *
     * @param orderId              订单ID
     * @param employeeRemarkIsRead 是否已读
     */
    public void updateEmployeeRemarkIsRead(Long orderId, Boolean employeeRemarkIsRead) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("employeeRemarkIsRead", employeeRemarkIsRead);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 员工更新订单中商品备注
     *
     * @param orderId        订单ID
     * @param index          商品索引号
     * @param employeeRemark 备注信息
     */
    public void updateProductEmployeeRemark(Long orderId, Integer index, String employeeRemark) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("productInfos." + index + ".employeeRemark", employeeRemark);
        update.set("productInfos." + index + ".employeeRemarkIsRead", false);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 编辑员工备注已读
     *
     * @param orderId              订单ID
     * @param index                商品索引号
     * @param employeeRemarkIsRead 是否已读
     */
    public void updateProductEmployeeRemarkIsRead(Long orderId, Integer index, Boolean employeeRemarkIsRead) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("productInfos." + index + ".employeeRemarkIsRead", employeeRemarkIsRead);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 更新商品中的申请退货数量
     *
     * @param orderId      订单ID
     * @param skuId        商品ID
     * @param applyNumber  申请退货数量
     * @param returnNumber 已经退货数量
     */
    public void updateProductReturnNumber(String orderId, Integer skuId, Integer applyNumber, Integer returnNumber) {
        Query query = new Query(where("_id").is(orderId).and("productInfos.skuId").is(skuId));
        Update update = new Update();
        update.set("productInfos.$.applyReturnNumber", applyNumber);
        if (returnNumber != null) {
            update.inc("productInfos.$.returnNumber", returnNumber);
            update.set("productInfos.$.afterSalesStatus", AfterSalesOrderStatusEnum.RETURNED_PAID.getValue());
        }
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    /**
     * 后台查询用户下单数量(待发货)
     *
     * @param userId 客户id
     * @return 数量
     */
    public Long countUserOrders(String userId) {
        // 统计待发货状态
        Query query = new Query(where("userId").is(userId).and("deleted").is(false).and("orderStatus").is(2));
        return mongoTemplate.count(query, OrderMasterInfo.class);
    }

    /**
     * 查最新
     *
     * @param limit 条数
     * @return List<OrderMasterInfo>
     */
    public List<OrderMasterInfo> findNew(int limit) {
        Query query = new Query(where("deleted").is(false).and("orderStatus").ne(1));
        query.with(Sort.by(Sort.Order.desc("createTime")));
        query.limit(limit);
        return mongoTemplate.find(query, OrderMasterInfo.class);
    }

    /**
     * 统计订单数量
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 数量
     */
    public Long countOrder(Date startTime, Date endTime) {
        Query query = new Query(where("deleted").is(false));
        if (startTime != null && endTime != null) {
            query.addCriteria(where("createTime").gte(startTime).lte(endTime));
        } else if (startTime != null) {
            query.addCriteria(where("createTime").gte(startTime));
        } else if (endTime != null) {
            query.addCriteria(where("createTime").lte(endTime));
        }
        return mongoTemplate.count(query, OrderMasterInfo.class);
    }

    /**
     * 统计订单销量
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 销量
     */
    public List<OrderMasterInfo> countSale(Date startTime, Date endTime) {
        Query query = new Query(where("orderStatus").nin(1, 6).and("deleted").is(false));
        if (startTime != null && endTime != null) {
            query.addCriteria(where("createTime").gte(startTime).lte(endTime));
        } else if (startTime != null) {
            query.addCriteria(where("createTime").gte(startTime));
        } else if (endTime != null) {
            query.addCriteria(where("createTime").lte(endTime));
        }
        return mongoTemplate.find(query, OrderMasterInfo.class);
    }

    public Long countOrderByUserIds(List<String> userIds) {
        Query query = new Query(where("userId").in(userIds).and("deleted").is(false));
        return mongoTemplate.count(query, OrderMasterInfo.class);
    }

    public List<OrderMasterInfo> countSaleByUserIds(List<String> userIds) {
        Query query = new Query(where("orderStatus").nin(1, 6).and("userId").in(userIds).and("deleted").is(false));
        return mongoTemplate.find(query, OrderMasterInfo.class);
    }

    public void editCustomerServiceRemark(Long orderId, String customerServiceRemark) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("customerServiceRemark", customerServiceRemark);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    public void updateShopId(String orderId, Integer shopId) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("shopId", shopId);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    public void removeOrderById(String orderId) {
        // 处于结束状态的订单可删除
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("deleted", true);
        update.set("updateTime", new Date());
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    public void pushOperationInfo(String orderId, OperationInfo operationInfo) {
        Query query = new Query(where("_id").is(orderId));
        Update update = new Update();
        update.set("updateTime", new Date());
        update.push("operationInfos", operationInfo);
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }

    public void setOneOrderExpress(String orderId, String expCode, String expNo, String expImage, String remark, Integer shopId) {
        Query query;
        if (shopId == null) {
            query = new Query(where("_id").is(orderId));
        }else {
            query = new Query(where("_id").is(orderId).and("shopId").is(shopId));
        }
        Update update = new Update();
        update.set("expressInfo.expCode", expCode);
        update.set("expressInfo.expNo", expNo);
        if (expImage != null) {
            update.set("expressInfo.expImage", expImage);
        }
        if (remark != null) {
            update.set("expressInfo.remark", remark);
        }
        update.set("updateTime", new Date());
        update.set("expressTime", new Date());
        update.set("orderStatus", OrderStatusEnum.UN_COMMIT.getValue());
        mongoTemplate.updateFirst(query, update, OrderMasterInfo.class);
    }
}
